package har.mon.ix.tiltka;

import java.io.IOException;

import android.app.Activity;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnLongClickListener;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

public class TiltReader extends Activity implements SensorEventListener {
    // User Interface
    private TextView mNovel;
    private ScrollView mScrollView;
    
    // Sensor related 
    private SensorManager mSensorMgr; 
    private Sensor mAccelerometer;
    private boolean mUserLongPressed = false;
    private float mSweetSpot;
    private final long mTHRESHOLD_DETERMINING_SCROLLSPEED = 31250000; 
    private long mLastUpdate = 0, mDifference = 0;
    SharedPreferences mPrefs;
        
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
     
        mScrollView = (ScrollView) findViewById(R.id.scrollView);
        mNovel = (TextView) findViewById(R.id.novel);
        
        mPrefs = getPreferences(MODE_PRIVATE);
  
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                
        mNovel.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                mUserLongPressed = true;  
                Toast.makeText(TiltReader.this, "Tilt to pause.  Long press again to change scroll angle.", Toast.LENGTH_LONG).show();
                return false;
            }
        });
        
        mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
        mAccelerometer = (Sensor) mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        
        if (getIntent().getAction().toString().equals("har.mon.ix.tiltka.LOAD_FILE")) {
            Uri uri = getIntent().getData();
            setLastOpenedUri(uri.toString());
            resetLastPosition();
            loadFile(getLastOpenedUri());
        } else if (!getLastOpenedUri().toString().equals("")) {
            loadFile(getLastOpenedUri());
        } else {
            loadFile(null);
        }
    }
    
    private int getLastPosition() {
        return mPrefs.getInt("landscape.lastPos", 0);
    }
                    
    private boolean setLastPosition() {
        SharedPreferences.Editor editor = mPrefs.edit();
        editor.putInt("landscape.lastPos", mScrollView.getScrollY());
        return editor.commit();
    }
    
    private boolean resetLastPosition() {
        SharedPreferences.Editor editor = mPrefs.edit();
        editor.putInt("landscape.lastPos", 0);
        return editor.commit();
    }
    
    private Uri getLastOpenedUri() {
        return Uri.parse(mPrefs.getString("lastOpenedFile", ""));
    }
    
    private boolean setLastOpenedUri(String uri) {
        SharedPreferences.Editor editor = mPrefs.edit();
        editor.putString("lastOpenedFile", uri);
        return editor.commit();
    }
     
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
            
    @Override
    public void onSensorChanged(SensorEvent event) {
        synchronized (this) {
            mDifference = event.timestamp - mLastUpdate;          
            if (mDifference >= mTHRESHOLD_DETERMINING_SCROLLSPEED) {
                scrollWhenTiltCloseToSweetSpot(event.values[2]);
                updateSweetSpotIfUserLongPressed(event.values[2]);
                mLastUpdate = event.timestamp;
            }
        }  
    }
    
    private void scrollWhenTiltCloseToSweetSpot(float angle) {
        if (angle >= mSweetSpot-2.55 && angle <= mSweetSpot+1.5) {       
            mScrollView.smoothScrollBy(0, 2);
        }
    }
    
    private void updateSweetSpotIfUserLongPressed(float angle) {
        if (mUserLongPressed) { 
            mSweetSpot = angle;
            mUserLongPressed = false; 
        }
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        mSensorMgr.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
        
        mScrollView.post(new Runnable() {
            @Override
            public void run() {
                mScrollView.scrollTo(0, getLastPosition());
            } 
        });
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        setLastPosition();
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        mSensorMgr.unregisterListener(this, mAccelerometer);
    }
    
    private void loadFile(Uri uri) { 
        try {
            FileLoader fl = null;
            fl = (uri != null) ? FileLoader.forUri(uri) : FileLoader.forInputStream((getAssets().open("metamorphosis.txt")));
            String text = fl.assetToString();            
            updateUI(text);
        } catch (java.io.FileNotFoundException e) {
            updateUI("Couldn't find your file.\nWas it renamed/moved/deleted?\nPick another! \n\nExiting in 5 seconds!");
            Handler handler = new Handler(); 
            handler.postDelayed(new Runnable() { 
                 public void run() { 
                     finish();
                 }
            }, 5000); 
        } catch (IOException e) {
            throw new RuntimeException(e);
        } 
    }
    
    private void updateUI(String text) {
        TextView tv = (TextView)findViewById(R.id.novel);
        tv.setText(text);
    }
}
